#!/usr/local/bin/perl
# -d:NYTProf
use strict;
use warnings;
use utf8;

use EV;
use JSON::XS;
use Digest::MD5 qw(md5_hex);
require HTTP::Status;
use Time::HiRes qw(gettimeofday);
use Getopt::Long;


our %params = (
	'debug' => 0,
	'srv-addr' => '127.0.0.1',
	'srv-port' => 12345,
	'unix-path' => '/var/tmp/chat',
	'login' => 'admin',
	'pass' => '12345',
#	prof => 1,
);
my @opt = (
	"debug:1",
	"srv-addr=s",
	"srv-port=i",
	"unix-path=s",
	"login=s",
	"pass=s",
);

my %con_all;
my $con_count = 1;

eval {
	Start();
};
if($@){
	print "error $@\n";
}
print "Normal exit\n";

################################################

sub Start {

	unless(GetOptions(\%params,@opt)){
		print "param parse error\n";
		return;
	}

	my $ServerSocket;
	my $UnixWaiter;

	if($params{'srv-addr'} && $params{'srv-port'}){
		unless($ServerSocket = SockCreate($params{'http-addr'},$params{'http-port'})){
			return;
		}
	}else{
		print "no server addr\n";
		return;
	}
	if($params{'unix-path'}){
		unless($UnixWaiter = PathCreate($params{'unix-path'})){
			return;
		}
	}
	
	binmode STDOUT,":utf8";
	$| = 1;
	
	send_message(login=>{login=>$params{'login'},pass=>$params{'pass'}});
	
	EV::loop;
}

sub SockCreate {
	my ($addr,$port) = @_;
	my $sock = new IO::Socket::INET(
			PeerHost =>  $addr,
			PeerPort =>  $port,
		);
	unless($sock){
		print "SOCK $@\n";
		return;
	}
	return $sock;
}
sub PathCreate {
	my ($path) = @_;
	my $sock = new IO::Socket::UNIX(
			Listen => 100,
			Local =>  $path,
		);
	unless($sock){
		print "SOCK $@\n";
		return;
	}
	
	# слушаем основной сокет
	return EV::io $sock, EV::READ, \&stream_path_handler;
}
sub stream_path_handler {
	my ($w,$rm) = @_;
    my $new = $w->fh->accept;
    unless($new){
		return 0;
	}
    my $nw = EV::io $new, EV::READ, \&read_path_handler;

	## сохраняем слушателя, буфер с принятыми данными
	$con_all{++$con_count} = $nw;
	$nw->data([$con_count,""]);
}
sub read_path_handler {
	my ($w, $m) = @_;
	# Получили данные
	my $buf;
	my $fh = $w->fh;
	if($fh->opened){
		$fh->recv($buf,1024);
	}
	if($buf){
		# есть данные, цепляем к предыдущим если есть
		$w->data->[1] .= $buf;
		while(my $cmd = PathParse(\$w->data->[1])){
			my $ret = ProcessCommand($cmd,$fh,\&send_sock_message);
			send_sock_message($fh,$ret) if $ret;
		}
	}else{
		delete $con_all{$w->data->[0]};
	}
}
sub PathParse {
	my ($rstr) = @_;
	my $i = index($$rstr,chr(0));
	if($i == -1){
		return 0;
	}
	my $str = substr($$rstr,0,$i,"");

	substr($$rstr,0,1,"");
	my $msg = decode_json($str);
	return $msg;
}


